package com.cskaoyan.aspect;

import com.cskaoyan.anno.AddLog;
import com.cskaoyan.bean.vo.BaseRespVo;
import com.cskaoyan.bean.MarketAdmin;
import com.cskaoyan.bean.MarketLog;
import com.cskaoyan.service.admin.MarketLogService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

/**
 * 日志的AOP
 *
 * @author Bowen Deng
 * @since 2022/06/27 08:49
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    MarketLogService marketLogService;

    @Autowired
    HttpServletRequest request;

    /**
     * 添加登陆日志
     *
     * @return void
     * @author Bowen Deng
     * @since 2022/06/27 2:28 下午
     */
    @Pointcut("execution(* com.cskaoyan.controller..*(..))")
    public void logPointcut() {
    }

    /**
     * 添加登陆日志,自定义一个AddLog注解，给需要增加日志的方法添加注解即可增加注解
     *
     * @param joinPoint
     * @return java.lang.Object
     * @author Bowen Deng
     * @since 2022/06/27 2:28 下午
     */
    @Around("logPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method handlerClass = signature.getMethod();
        if (handlerClass.isAnnotationPresent(AddLog.class)) {
            AddLog addLog = handlerClass.getAnnotation(AddLog.class);
            BaseRespVo proceed = (BaseRespVo) joinPoint.proceed();
            Subject subject = SecurityUtils.getSubject();
            PrincipalCollection principals = subject.getPrincipals();
            MarketLog marketLog = getMarketLog();
            if (principals == null) {
                marketLog.setAdmin("匿名用户");
            } else {
                MarketAdmin primaryPrincipal = (MarketAdmin) principals.getPrimaryPrincipal();
                marketLog.setAdmin(primaryPrincipal.getUsername());
            }
            marketLog.setType(addLog.type());
            marketLog.setComment(addLog.comment());
            marketLog.setAction(addLog.value());
            marketLog.setIp(request.getRemoteAddr());
            if (proceed.getErrno() == 0) {
                marketLog.setStatus(true);
            } else {
                marketLog.setStatus(false);
            }
            //具体业务逻辑，登陆业务
            if (addLog.value().equals("登陆")) {
                if (proceed.getErrno() == 0) {
                    marketLog.setResult("登陆成功");
                } else {
                    marketLog.setResult("用户名或密码不正确");
                }
            }
            //具体业务，管理员相关业务
            if (addLog.value().contains("管理员")) {
                if(proceed.getErrno()!=0){
                    return proceed;
                }
                Object[] args = joinPoint.getArgs();
                MarketAdmin admin = null;
                if (addLog.value().contains("添加")) {
                    admin = (MarketAdmin) proceed.getData();
                } else {
                    admin = (MarketAdmin) args[0];
                }
                marketLog.setResult(addLog.result() + ":" + admin.getUsername());
            }

            //具体业务，订单相关
            if(addLog.type()==2){
                Object[] args = joinPoint.getArgs();
                Map map = (Map) args[0];
                Integer orderId = (Integer) map.get("orderId");
                marketLog.setResult(addLog.result()+orderId.toString());
            }

            marketLogService.addLog(marketLog);
            return proceed;

        }
        Object proceed = joinPoint.proceed();
//        marketLogService.addLog(marketLog);
        return proceed;
    }

    /**
     * marketlog有些值是固定的，抽取一个方法方便一些
     *
     * @return com.cskaoyan.bean.MarketLog
     * @author Bowen Deng
     * @since 2022/06/29 11:04 上午
     */
    private static MarketLog getMarketLog() {
        MarketLog marketLog = new MarketLog();
        marketLog.setAddTime(new Date());
        marketLog.setDeleted(false);
        marketLog.setUpdateTime(new Date());
        return marketLog;
    }
}
